home *** CD-ROM | disk | FTP | other *** search
- /*
- * B G _ C D P D N T . C -- this is a library module of BG.C and is used
- * -- along with some #defines to make the
- * -- program portable, the C-Dependent part of
- * -- the program, i.e. are we compiling for
- * -- Microsoft-C, Mix-C, or Turbo-C.
- * -- Mostly graphics routines in here. See COMP.H
- * -- to see which compiler we are using.
- * O F Ransen, 9th January 1993
- */
-
- #include "comp.h"
- #include <stdlib.h>
- #include <stdio.h>
- #include <bios.h>
- #include <conio.h>
- #include <time.h>
- #include <signal.h>
- #include "bg.h"
-
- /**************************************************************************/
-
- void Go_Text_Mode ()
- /*
- PURPOSE: To go back to the original text mode
- */
- {
- #if TURBO_C
- closegraph () ;
- #elif MS_C
- _setvideomode (_DEFAULTMODE) ;
- #elif MIX_C
- setvideomode (DEFAULTMODE) ;
- #endif
- }
-
- /**************************************************************************/
-
- #define EGA_YPIXELS 200
-
- void Get_Display_Config (Disp_Cfg_t* Cfg)
- /*
- PURPOSE: To fill out the Cfg structure with data about the current display.
- */
- {
- #if MIX_C
-
- #define MIX_CHAR_WIDE 8 /* Pixel size of chars... */
- #define MIX_CHAR_HIGH 8 /* ...in graphics mode. */
- (void)getvconfig (&Mix_Cfg) ;
- Cfg->X_Pixels = Mix_Cfg.xpixels ;
- Cfg->Y_Pixels = Mix_Cfg.ypixels ;
- Cfg->Aspect_H = Mix_Cfg.aspect_h ;
- Cfg->Aspect_V = Mix_Cfg.aspect_v ;
- Cfg->Char_Wide = MIX_CHAR_WIDE ;
- Cfg->Char_High = MIX_CHAR_HIGH ;
- Cfg->Text_Cols = Mix_Cfg.xpixels / Cfg->Char_Wide ;
- Cfg->Text_Rows = Mix_Cfg.ypixels / Cfg->Char_High ;
-
- #elif MS_C
-
- _getvideoconfig (&Ms_Cfg) ;
- Cfg->X_Pixels = Ms_Cfg.numxpixels ;
- Cfg->Y_Pixels = Ms_Cfg.numypixels ;
-
- if (Cfg->Y_Pixels == EGA_YPIXELS) {
- Cfg->Aspect_H = 20 ;
- Cfg->Aspect_V = 10 ;
- } else /* VGA */ {
- Cfg->Aspect_H = 20 ;
- Cfg->Aspect_V = 20 ;
- }
- Cfg->Text_Cols = Ms_Cfg.numtextcols ;
- Cfg->Text_Rows = Ms_Cfg.numtextrows ;
- Cfg->Char_Wide = Ms_Cfg.numxpixels / Cfg->Text_Cols ;
- Cfg->Char_High = Ms_Cfg.numypixels / Cfg->Text_Rows ;
-
- #elif TURBO_C
- Cfg->X_Pixels = getmaxx() + 1 ;
- Cfg->Y_Pixels = getmaxy() + 1 ;
- if (Cfg->Y_Pixels == EGA_YPIXELS) {
- Cfg->Aspect_H = 20 ;
- Cfg->Aspect_V = 10 ;
- } else /* VGA */ {
- Cfg->Aspect_H = 20 ;
- Cfg->Aspect_V = 20 ;
- }
- Cfg->Char_Wide = textwidth ("A") ;
- Cfg->Char_High = textheight("A") ;
- Cfg->Text_Cols = Cfg->X_Pixels / Cfg->Char_Wide ;
- Cfg->Text_Rows = Cfg->Y_Pixels / Cfg->Char_High ;
- #endif
- }
-
- /**************************************************************************/
-
- void Draw_Line (short x1, short y1, short x2, short y2, short Col)
- /*
- PURPOSE: To draw a line from (x0,y0)-(x1-y1) of Col.
- */
- {
- #if MIX_C
- (void)pen_color (Col) ;
- move_to (x1,y1) ;
- line_to (x2,y2) ;
- #elif MS_C
- _setcolor (Col) ;
- _moveto (x1,y1) ;
- _lineto (x2,y2) ;
- #elif TURBO_C
- setcolor (Col) ;
- line (x1,y1,x2,y2) ;
- #endif
- }
-
- /**************************************************************************/
-
- void Draw_Rect (short x0, short y0, short Wide, short High, short Col)
- /*
- PURPOSE: To draw an unfilled rectangle of Col.
- NOTES: 1) The horizontal lines of the rectangle should have exactly
- Wide pixels, and the vertical lines exactly High pixels.
- 2) The extents of the rectangle are
- (x0,y0) -- (x0+Wide-1,y0+High-1)
- */
- {
- #if MIX_C
- (void)pen_color (Col) ;
- move_to (x0,y0) ;
- box (Wide,High,FALSE) ;
- #elif MS_C
- _setcolor (Col) ;
- _rectangle (_GBORDER,x0,y0,x0+Wide-1,y0+High-1) ;
- #elif TURBO_C
- setcolor (Col) ;
- rectangle (x0,y0,x0+Wide-1,y0+High-1) ;
- #endif
- }
-
- /**************************************************************************/
-
- void Fill_Rect (short x0, short y0, short Wide, short High, short Col)
- /*
- PURPOSE: To draw a filled rectangle of Col. See notes for Draw_Rect.
- */
- {
- #if MIX_C
- (void)pen_color (Col) ;
- move_to (x0,y0) ;
- box (Wide,High,TRUE) ;
- #elif MS_C
- _setcolor (Col) ;
- _rectangle (_GFILLINTERIOR,x0,y0,x0+Wide-1,y0+High-1) ;
- #elif TURBO_C
- int Rect[8] ;
- setcolor (Col) ;
- setfillstyle (SOLID_FILL,Col) ;
- Rect[0] = x0 ; Rect[1] = y0 ;
- Rect[2] = x0+Wide-1 ; Rect[3] = y0 ;
- Rect[4] = x0+Wide-1 ; Rect[5] = y0+High ;
- Rect[6] = x0 ; Rect[7] = y0+High ;
- fillpoly (4,Rect) ;
- #endif
- }
-
- /**************************************************************************/
-
- void Fill_Poly (short N_Points, short* Points, short Colour)
- /*
- PURPOSE: To do a solid poly fill.
- */
- {
- setfillstyle (SOLID_FILL,Colour) ;
- fillpoly (N_Points,(int*)Points) ;
- }
-
- /**************************************************************************/
-
- void Draw_Point (short x, short y, short c)
- /*
- PURPOSE: To draw a point on the screen.
- */
- {
- #if MIX_C
- writedot (y,x,c) ;
- #elif MS_C
- _setcolor (c) ;
- _setpixel (x,y) ;
- #elif TURBO_C
- putpixel (x,y,c) ;
- #endif
- }
-
- /**************************************************************************/
-
- #if MS_C
- static char Solid_Fill_Mask[8] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF} ;
- #endif
-
- void Set_Solid_Fill_Style (void)
- /*
- PURPOSE: To set the pattern which will be used in filling to solid.
- */
- {
- #if MS_C
- _setfillmask (Solid_Fill_Mask) ;
- #elif TURBO_C
- setfillstyle (SOLID_FILL,0) ;
- #endif
- }
-
- /**************************************************************************/
-
- void Draw_Ellipse (short X_Center, short Y_Center,
- short X_Rad, short Y_Rad, short Col)
- /*
- PURPOSE: To draw an ellipse at a centre with x and y radii, of Col.
- */
- {
- #if MIX_C
- move_to (X_Center,Y_Center) ;
- (void)pen_color (Col) ;
- ellipse (X_Rad,Y_Rad,Col) ;
- #elif MS_C
- /* Check the following for actual extents of the ellipse... */
- _setcolor (Col) ;
- _ellipse (_GBORDER,X_Center-X_Rad,Y_Center-Y_Rad,
- X_Center+X_Rad,Y_Center+Y_Rad) ;
- #elif TURBO_C
- setcolor (Col) ;
- ellipse (X_Center,Y_Center,0,360,X_Rad,Y_Rad) ;
- #endif
- }
-
- /**************************************************************************/
-
- void Fill_Ellipse (short X_Center, short Y_Center,
- short X_Rad, short Y_Rad, short Col)
- /*
- PURPOSE: To draw a solid filled ellipse at a centre with x and y radii.
- */
- {
- #define LIMIT 1
- #if MIX_C
- /* MIX_C does not fill well, so we draw concentric circles */
- (void)pen_color (Col) ;
- move_to (X_Center,Y_Center) ;
- do {
- ellipse (X_Rad,Y_Rad,Col) ;
- if (X_Rad > LIMIT) {
- X_Rad-- ;
- }
- if (Y_Rad > LIMIT) {
- Y_Rad-- ;
- }
- } while ((X_Rad > LIMIT) || (Y_Rad > LIMIT)) ;
- #elif MS_C
- _setcolor (Col) ;
- _ellipse (_GFILLINTERIOR,X_Center-X_Rad,Y_Center-Y_Rad,
- X_Center+X_Rad,Y_Center+Y_Rad) ;
- do {
- _ellipse (_GBORDER,X_Center-X_Rad,Y_Center-Y_Rad,
- X_Center+X_Rad,Y_Center+Y_Rad) ;
- if (X_Rad > LIMIT) {
- X_Rad-- ;
- }
- if (Y_Rad > LIMIT) {
- Y_Rad-- ;
- }
- } while ((X_Rad > LIMIT) || (Y_Rad > LIMIT)) ;
- #elif TURBO_C
- setcolor (Col) ; /* So that the outline is correct colour too */
- setfillstyle (SOLID_FILL,Col) ;
- fillellipse (X_Center,Y_Center,X_Rad,Y_Rad) ;
- #endif
- }
-
- /**************************************************************************/
-
- void Graf_Text (short Row, short Col, char* String, short Color)
- /*
- PURPOSE: To output a string at Row, Col on the graphics screen.
- */
- {
- extern Disp_Cfg_t Disp_Cfg ;
-
- #if MS_C
- Row = Row + 1 ;
- Col = Col + 1 ;
- if ((Row == Disp_Cfg.Text_Rows) && (Col == Disp_Cfg.Text_Cols)) {
- /* MSC does not allow you to put a char here, scrolls! */
- Col-- ;
- }
- _settextcolor (Color) ;
- _settextposition (Row,Col) ;
- _outtext (String) ;
-
- #elif TURBO_C
- Fill_Rect (Col*Disp_Cfg.Char_Wide,Row*Disp_Cfg.Char_High,
- textwidth (String),textheight (String),BLACK) ;
- setcolor (Color) ;
- outtextxy (Col*Disp_Cfg.Char_Wide,Row*Disp_Cfg.Char_High,String) ;
-
- #endif
- }
-
- /**************************************************************************/
-
- void Text_At_Pixel (short x, short y, char* String, short Colour)
- /*
- PURPOSE: To draw pixel algined text of a certain colour.
- */
- {
- setcolor (Colour) ;
- outtextxy (x,y,String) ;
- }
- /**************************************************************************/
-
- void Error_Exit (char* Last_Words)
- /*
- PURPOSE: To speak the Last_Words and expire.
- */
- {
- extern FILE* Rec_File ;
- extern boolean Debugging ;
- extern char Globerr[GERR_LEN] ;
-
- printf ("\nERROR: %s",Last_Words) ;
- printf ("\nGloberr = %s",Globerr) ;
- printf ("\nHit a key") ; (void)getch () ;
- closegraph () ;
- printf ("\nERROR: %s",Last_Words) ;
- printf ("\nGloberr = %s",Globerr) ;
- if ((Rec_File != NULL) && (Debugging)) {
- fprintf (Rec_File,"\nERROR: %s",Last_Words) ;
- fprintf (Rec_File,"\nGloberr = %s",Globerr) ;
- fclose (Rec_File) ;
- }
- exit (1) ; /* Exit from error condition */
- }
-
- /**************************************************************************/
-
- void Init_Rannum_Gen (void)
- /*
- PURPOSE: To initialise the random number generator so that the same
- sequence will be used every time.
- */
- {
- srand (1) ;
- }
-
- /**************************************************************************/
-
- void Randomise (void)
- /*
- PURPOSE: To initialise the random number generator so that a different
- sequence will be used every time the program is run.
- */
- {
- time_t t ;
- (void)time (&t) ;
- srand ((uint)t) ;
- }
-
- /**************************************************************************/
-
- int Int_Rand_Range (int least, int most)
- /*
- PURPOSE : To return a random integer in the range specified.
- NOTES : 1) This has been carefully written to include least and most
- in the return values
- 2) rand returns an integer in the range 0...32767 in Microsoft
- C and 0..16383 in Power C. The Power C manual says it is
- 32767, but that appears to be wrong.
- */
- {
- long delta,number,r ;
-
- delta = (long)most - (long)least + (long)1 ;
- r = (long)rand () ;
- number = (long)least + ((delta*r)/(long)RAND_MAX) ;
-
- if ((number < least) || (number > most)) {
- return (Int_Rand_Range (least,most)) ;
- } else {
- return ((int)number) ;
- }
- }
-
- /***********************************************************************/
-
- void Set_Ctl_C_Handler (void)
- /*
- PURPOSE: To install the function which will be called when the user
- hits control-C or control-break ;
- */
- {
- (void)signal(SIGINT,Ctl_C_Handler) ;
- }
-
- /***********************************************************************/
-
- void Ctl_C_Handler (void)
- /*
- PURPOSE: To get all the Ctl-Cs that arrive and if the user REALLY wants
- to exit we let him say so by hitting ESC, else we carry on.
- */
- {
- extern FILE* Rec_File ;
-
- Print_Message (CTLC_MSG) ;
- (void)signal (SIGINT,SIG_IGN) ; /* Disable Ctl-C processing for now */
- if (getch() == ESC_KEY) {
- Go_Text_Mode () ;
- if (Rec_File != NULL) {
- fprintf (Rec_File,"\nUser hit Ctl-c or Ctl-break.\n") ;
- fclose (Rec_File) ;
- }
- exit (1) ; /* Exit because of control-c */
- } else {
- Clear_Help_Line () ;
- (void)signal (SIGINT,Ctl_C_Handler) ;
- }
- }
-
- /*************************************************************************/
-